package com.strive.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.strive.common.model.dto.SysMenu;
import com.strive.common.model.dto.SysPower;
import com.strive.common.model.dto.SysRoleMenu;
import com.strive.common.service.impl.SuperServiceImpl;
import com.strive.user.mapper.SysMenuMapper;
import com.strive.user.mapper.SysPowerMapper;
import com.strive.user.mapper.SysPowerRoleMapper;
import com.strive.user.mapper.SysRoleMenuMapper;
import com.strive.user.service.ISysMenuService;
import com.strive.user.service.ISysRoleMenuService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: bingcun.chen
 * @Date: 2022/2/23 13:35
 * @Version 1.0
 */
@Service
public class SysMenuServiceImpl extends SuperServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {
    @Resource
    private ISysRoleMenuService roleMenuService;

    @Autowired
    private SysPowerMapper sysPowerMapper;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysPowerRoleMapper sysPowerRoleMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setMenuToRole(Long roleId, Set<Long> menuIds) {
        roleMenuService.delete(roleId, null);

        if (CollectionUtils.isNotEmpty(menuIds)) {
            List<SysRoleMenu> roleMenus = new ArrayList<>(menuIds.size());
            menuIds.forEach(menuId -> roleMenus.add(new SysRoleMenu(roleId, menuId)));
            roleMenuService.saveBatch(roleMenus);
        }
    }

    /**
     * 角色菜单列表
     * @param roleIds
     * @return
     */
    @Override
    public List<SysMenu> findByRoles(Set<Long> roleIds) {
        return roleMenuService.findMenusByRoleIds(roleIds, null);
    }

    /**
     * 角色菜单列表
     * @param roleIds 角色ids
     * @param roleIds 是否菜单
     * @return
     */
    @Override
    public List<SysMenu> findByRoles(Set<Long> roleIds, Integer type) {
        return roleMenuService.findMenusByRoleIds(roleIds, type);
    }

    @Override
    public List<SysMenu> findByRoleCodes(Set<String> roleCodes, Integer type) {
        return roleMenuService.findMenusByRoleCodes(roleCodes, type);
    }

    @Override
    public List<SysMenu> findMyMenuAndPowers(Set<String> roleSet) {
        List<SysMenu> menusList = this.findByRoleCodes(roleSet, null);
        //根据角色构建权限数据
        List<SysPower> sysPowerList = this.findPowersByRoles(roleSet);
        buildPowers(menusList,sysPowerList);
        return menusList;
    }

    @Override
    public List<SysPower> findPowersByRoles(Set<String> roleSet) {
        return sysPowerMapper.findPowersByRoles(roleSet);
    }

    /**
     * 查询所有菜单
     */
    @Override
    public List<SysMenu> findAll() {
        List<SysMenu> list = baseMapper.findAllMenus();

        if(CollectionUtils.isEmpty(list))return Lists.newArrayList();
        List<SysPower> sysPowers = sysPowerMapper.selectList(null);

        //判断是否有权限
        if(CollectionUtils.isNotEmpty(list) && CollectionUtils.isNotEmpty(sysPowers)){
            buildPowers(list, sysPowers);
        }
        return list;
    }


     /**
      * 构建权限
      * @param menusList 菜单
      * @param sysPowers 权限
     */
    public void buildPowers(List<SysMenu> menusList, List<SysPower> sysPowers) {
        Map<String, List<SysPower>> sysPowersMap = sysPowers.stream().collect(Collectors.groupingBy(ns -> ns.getMenu()));
        for (SysMenu sysMenu : menusList) {
            String menuId = String.valueOf(sysMenu.getId());
            if(sysPowersMap.containsKey(menuId)){
                List<SysPower> childrenSysPowers = sysPowersMap.get(menuId);
                sysMenu.setPowers(childrenSysPowers);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMenusPowers(Long id) {
        List<Long> ids = new ArrayList<>();
        ids.add(id);
        List<SysMenu> allMenus = this.findAll();
        //通过id找到其对应的子菜单
        findChildNode(id,allMenus,ids);

        //批量删除菜单
        baseMapper.deleteBatchIds(ids);

        //批量删除权限信息
        sysPowerMapper.deleteByMenuIds(ids);

        //删除菜单角色
        sysRoleMenuMapper.deleteBatchIds(ids);

        //删除菜单权限
        sysPowerRoleMapper.deleteBatchIds(ids);
    }

    private void findChildNode(Long id,List<SysMenu> allMenus,List<Long> ids) {
        List<SysMenu> menusList = allMenus.stream().filter(ns -> Objects.equals(ns.getParent(), id)).collect(Collectors.toList());
        for (SysMenu sysMenu : menusList) {
            Long munuId = sysMenu.getId();
            ids.add(munuId);
            findChildNode(sysMenu.getId(),allMenus,ids);
        }
    }

    /**
     * 查询所有一级菜单
     */
    @Override
    public List<SysMenu> findOnes() {
        return baseMapper.selectList(
                new QueryWrapper<SysMenu>()
                        .eq("type", 1)
                        .orderByAsc("sort")
        );
    }
}
